/*
 ============================================================================
 Name		: LlcpReceiveHandler.cpp
 Author	  : 
 Version	 : 1.0
 Copyright   : 
 Description : CLlcpReceiveHandler implementation
 ============================================================================
 */

#include "LlcpReceiveHandler.h"
#include "P2PMessageSupplier.h"

#include <llcpconnorientedtransporter.h>
#include "Log.h"

CLlcpReceiveHandler::CLlcpReceiveHandler(MLlcpConnOrientedTransporter* aTransporter,
		MP2PMessageSupplier* aMessageSupplier) :
	CActive(EPriorityStandard), // Standard priority
	iTransporter(aTransporter),
	iMessageSupplier(aMessageSupplier)
	{
	}

CLlcpReceiveHandler* CLlcpReceiveHandler::NewLC(MLlcpConnOrientedTransporter* aTransporter,
		MP2PMessageSupplier* aMessageSupplier)
	{
	CLlcpReceiveHandler* self = new (ELeave) CLlcpReceiveHandler(aTransporter,
			aMessageSupplier);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CLlcpReceiveHandler* CLlcpReceiveHandler::NewL(MLlcpConnOrientedTransporter* aTransporter,
		MP2PMessageSupplier* aMessageSupplier)
	{
	CLlcpReceiveHandler* self = CLlcpReceiveHandler::NewLC(aTransporter,
			aMessageSupplier);
	CleanupStack::Pop(); // self;
	return self;
	}

void CLlcpReceiveHandler::ConstructL()
	{
	CActiveScheduler::Add(this); // Add to scheduler
	
	iState = EConnected;
	
	User::LeaveIfError( StartReceive() );
	}

TInt CLlcpReceiveHandler::StartReceive()
	{
	if (IsActive())
		{
		LOG1(_L8("ERROR! Receiver, start receive called when already receiving."));
		return KErrInUse;
		}
	if ( iState != EConnected )
		{
		LOG1(_L8("ERROR! Receiver, start receive called when not in \"connected\" state."));
		return KErrNotReady;
		}
	TInt length = 0;
	length = iTransporter->SupportedDataLength();
			
	LOG2(_L8("Receiver, supported data length == %d"), length);
	if ( length > 0 )
		{
		iReceiveBuf.Close();
		TInt error = iReceiveBuf.Create( length );
				
		if ( error == KErrNone )
			{
			LOG1(_L8("Receiver, calling receive"));
			iTransporter->Receive( iStatus, iReceiveBuf );
			SetActive();
			iState = EReceiving;
			return KErrNone;
			}
		else
			{
			LOG1(_L8("Receiver, unable to allocate receive buffer."));
			return error;
			}
		}
	else
		{
		// if length is 0 or negative, LLCP link is destroyed.
		LOG1(_L8("Receiver, supported length <= 0, link destroyed."));
		return KErrNotReady;
		}
	}


CLlcpReceiveHandler::~CLlcpReceiveHandler()
	{
	iReceiveBuf.Close(),
	Cancel(); // Cancel any request, if outstanding
	// Delete instance variables if any
	}

void CLlcpReceiveHandler::DoCancel()
	{
	if (iState == EReceiving)
		{
		iTransporter->ReceiveCancel();
		}
	}

void CLlcpReceiveHandler::RunL()
	{
	switch (iState)
		{
		case EConnected:
			{
			break;
			}
		case EReceiving:
			{
			LOG3(_L8("Receiver, error == %d, message length == %d"), iStatus.Int(), iReceiveBuf.Length());
			if (iStatus.Int() == KErrNone)
				{
				iMessageSupplier->MessageReceived(iReceiveBuf);
				iState = EConnected;
				StartReceive();
				}
			else
				{
				iState = EError;
				}
			break;
			}
		default:
			{
			break;
			}
		}
	}

TInt CLlcpReceiveHandler::RunError(TInt aError)
	{
	return aError;
	}
